package com.gonsin.gmessage.logic.websocket;

import com.gonsin.gmessage.annotations.GMessageEnvironment;
import com.gonsin.gmessage.logic.model.GMessageModel;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;

import javax.websocket.Session;
import java.io.IOException;
import java.util.Objects;
import java.util.Set;

/**
 * 每一个连接表示一个session，session存储每个连接独有的数据
 */
@Slf4j
public class WebSocketSession implements Comparable<WebSocketSession> {

    private final SessionInfo sessionInfo;          // 存储连接信息

    private final Session session;

    private final WebSocketSessionContainer webSocketSessionContainer;

    public WebSocketSession(Session session, WebSocketSessionContainer webSocketSessionContainer){
        this.webSocketSessionContainer = webSocketSessionContainer;
        this.sessionInfo = new SessionInfo();
        this.session = session;
        this.sessionInfo.setSessionId(session.getId());
    }

    public void channelActive() throws Exception {
//        InetSocketAddress address = (InetSocketAddress)session..channel().remoteAddress();
//        this.sessionInfo.setRemoteAddress(address.toString());
    }

    public void channelRead(MessageBo message) throws Exception {
        try{
            if(WebSocketCmd.Cmd.CLIENT.equals(message.getCmd().getCmd())){

                // 心跳，不做任何处理
                if(WebSocketCmd.SubCmd.HEART.equals(message.getCmd().getSubcmd())){
                    return;
                }

                // 注册指令
                if(WebSocketCmd.SubCmd.REGISTER.equals(message.getCmd().getSubcmd())){
                    String registerCmd = (String) message.getArgs().get("cmd");
                    String zoom = (String) message.getArgs().get("zoom");
                    webSocketSessionContainer.addCmdSession(zoom, registerCmd, this);
                    return;
                }

                // 注销指令
                if(WebSocketCmd.SubCmd.UNREGISTER.equals(message.getCmd().getSubcmd())){
                    String registerCmd = (String) message.getArgs().get("cmd");
                    String zoom = (String) message.getArgs().get("zoom");
                    webSocketSessionContainer.removeCmdSession(zoom, registerCmd, this);
                    return;
                }

                // 注销指令
                if(WebSocketCmd.SubCmd.REGISTER_USER.equals(message.getCmd().getSubcmd())){
                    String username = (String) message.getArgs().get("username");
                    webSocketSessionContainer.addUsernameSession(username, this);
                    return;
                }
            }
        } catch(Exception ex){
            // 记录websocket出错情况
//            warningService.sendWarning(ErrorTarget.WEBSOCKET, "WebSocket处理错误，【" + new Gson().toJson(message) + "】", ex);
            throw ex;
        } finally {
//            super.channelRead(ctx, msg);
        }
    }

    public Set<SessionInfo.ZoomCmd> getRegisteredCmd() {
        return sessionInfo.getRegisteredCmd();
    }

    public String getUsername() {
        return sessionInfo.getUsername();
    }

    /**
     * 记录当前session已经注册过的指令
     */
    void addToCmd(String zoom, String cmd) {
        sessionInfo.getRegisteredCmd().add(new SessionInfo.ZoomCmd(zoom, cmd));
    }

    /**
     * 移除已注册的指令
     */
    void removeCmd(String zoom, String cmd) {
        sessionInfo.getRegisteredCmd().removeIf(zr -> Objects.equals(cmd, zr.getCmd()) && Objects.equals(zoom, zr.getZoom()));
    }

    /**
     * 发送消息
     */
    void write(GMessageModel message) {
        if(GMessageEnvironment.LOG){
            log.info("向 zoom = 【{}】发送消息【{}】", getUsername(), message);
        }
        try {
            session.getBasicRemote().sendText(new Gson().toJson(message));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    void write(String payload){
        try {
            session.getBasicRemote().sendText(payload);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取session信息
     */
    public SessionInfo getSessionInfo() {
        return sessionInfo;
    }

    /**
     * 设置用户名
     */
    public void setUsername(String username) {
        sessionInfo.setUsername(username);
    }

    @Override
    public int compareTo(WebSocketSession webSocketSession) {
        return webSocketSession.toString().compareTo(this.toString());
    }

    /**
     * session掉线
     */
    public void channelInactive() {
        webSocketSessionContainer.removeSession(this);
    }

    public void exceptionCaught(Throwable error) {
        sessionInfo.setExceptionCount(sessionInfo.getExceptionCount() + 1);
        sessionInfo.setLastException(error.toString());
    }
}
